﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace HYPreviewer
{
	public class DrawingPlotter
	{
		public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<CurveInfo> curves)
		{
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_Curves = curves;
		}

		public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<TextNoteInfo> textNotes)
		{
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_TextNotes = textNotes;
		}

		public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<CurveInfo> curves, List<TextNoteInfo> textNotes)
		{
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_Curves = curves;
			this.m_TextNotes = textNotes;
		}

		public DrawingPlotter(System.Windows.Forms.Control control, Graphics graphics, List<CurveInfo> curves, List<TextNoteInfo> textNotes, List<FillRegion> fillRegions)
		{
			this.m_Control = control;
			this.m_Graphics = graphics;
			this.m_Curves = curves;
			this.m_TextNotes = textNotes;
			this.m_FillRegions = fillRegions;
		}

		public void Draw()
		{
			if (this.m_Curves.Count < 1 && this.m_TextNotes.Count < 1 && this.m_FillRegions.Count < 1)
			{
				return;
			}
			this.m_Graphics.SmoothingMode = SmoothingMode.HighQuality;
			this.m_Graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
            this.m_Graphics.Clear(System.Drawing.Color.White);
			Size size = this.m_Control.Size;
			Size size2 = new Size((int)(0.9 * (double)size.Width), (int)(0.9 * (double)size.Height));
			Transform trans = this.ComputerTransMatrix(size2);
			foreach (TextNoteInfo textNoteInfo in this.m_TextNotes)
			{
				this.DrawText(textNoteInfo, trans);
			}
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				this.DrawFillRegion(fillRegion, trans);
			}
			foreach (CurveInfo curveInfo in this.m_Curves)
			{
				Pen penWithCurveInfo = this.GetPenWithCurveInfo(curveInfo.Color, curveInfo.LineWidth);
				Line line = curveInfo.CurveObj as Line;
				if (null != line)
				{
					this.DrawLine(penWithCurveInfo, line, trans);
				}
				else
				{
					Arc arc = curveInfo.CurveObj as Arc;
					if (null != arc)
					{
						this.DrawArc(penWithCurveInfo, arc, trans);
					}
					else
					{
						NurbSpline nurbSpline = curveInfo.CurveObj as NurbSpline;
						if (null != nurbSpline)
						{
							IList<XYZ> ctrlPoints = nurbSpline.CtrlPoints;
							for (int i = 1; i < ctrlPoints.Count; i++)
							{
								this.DrawLine(penWithCurveInfo, ctrlPoints[i - 1], ctrlPoints[i], trans);
							}
						}
					}
				}
			}
		}

		protected Pen GetPenWithCurveInfo(PenColor penColor, float lineWidth)
		{
			return new Pen(this.PenColorToColor(penColor), lineWidth);
		}

        protected System.Drawing.Color PenColorToColor(PenColor penColor)
		{
            System.Drawing.Color white = System.Drawing.Color.White;
			switch (penColor)
			{
			case PenColor.PC_Red:
				return System.Drawing.Color.Red;
			case PenColor.PC_Blue:
				return System.Drawing.Color.Blue;
			case PenColor.PC_Green:
				return System.Drawing.Color.Green;
			case PenColor.PC_Gray:
				return System.Drawing.Color.Gray;
			case PenColor.PC_Yellow:
				return System.Drawing.Color.Yellow;
			case PenColor.PC_Black:
				return System.Drawing.Color.Black;
			}
			return System.Drawing.Color.White;
		}

		private Transform ComputerTransMatrix(Size size)
		{
			Transform identity = Transform.Identity;
			identity.Origin = XYZ.Zero;
			identity.BasisX = XYZ.BasisX;
			identity.BasisY = -XYZ.BasisY;
			identity.BasisZ = XYZ.BasisZ;
			BoundingBoxUV boundingBox = this.GetBoundingBox();
			UV max = boundingBox.Max;
			UV min = boundingBox.Min;
			double num = (double)size.Width / (max.U - min.U);
			double num2 = (double)size.Height / (max.V - min.V);
			double num3 = (num <= num2) ? num : num2;
			Transform transform = Transform.Identity;
			transform = transform.ScaleBasis(num3);
			Transform transform2 = RevitVersionFuncs.CreateTranslation(new XYZ((min.U + max.U) / 2.0, (min.V + max.V) / 2.0, 0.0));
			return Transform.Identity.Multiply(identity.Inverse).Multiply(transform).Multiply(transform2.Inverse);
		}

		protected BoundingBoxUV GetBoundingBox()
		{
			BoundingBoxUV boundingBoxUV = null;
			List<EdgeInfo> list = new List<EdgeInfo>();
			foreach (CurveInfo curveInfo in this.m_Curves)
			{
				list.Add(new EdgeInfo(curveInfo.CurveObj, false));
			}
			foreach (FillRegion fillRegion in this.m_FillRegions)
			{
				list.AddRange(fillRegion.EdgeLoop);
			}
			foreach (EdgeInfo edgeInfo in list)
			{
				if (edgeInfo.StartPoint != null && edgeInfo.EndPoint != null)
				{
					if (Geometry.IsEqual(edgeInfo.Bulge, 0.0))
					{
						if (boundingBoxUV == null)
						{
							boundingBoxUV = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
						}
						else
						{
							BoundingBoxUV box = Geometry.CalculateBoundingBox2D(edgeInfo.StartPoint, edgeInfo.EndPoint);
							boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box);
						}
					}
					else
					{
						XYZ startPoint = edgeInfo.StartPoint;
						XYZ endPoint = edgeInfo.EndPoint;
						XYZ ptCenter = null;
						XYZ normal = XYZ.BasisZ;
						double radius = 0.0;
						double num = 0.0;
						double num2 = 0.0;
						Geometry.GetArcInfoWithBulge(startPoint, endPoint, edgeInfo.Bulge, ref ptCenter, ref radius, ref num, ref num2);
						if (Geometry.LessThan(edgeInfo.Bulge, 0.0))
						{
							normal = -XYZ.BasisZ;
						}
						if (boundingBoxUV == null)
						{
							boundingBoxUV = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
						}
						else
						{
							BoundingBoxUV box2 = Geometry.CalculateBoundingBox2D(startPoint, endPoint, ptCenter, normal, radius);
							boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box2);
						}
					}
				}
			}
			foreach (TextNoteInfo textNoteInfo in this.m_TextNotes)
			{
				XYZ xyz = XYZ.BasisX * textNoteInfo.m_BoundingBoxWidth / 2.0;
				XYZ xyz2 = XYZ.BasisY * textNoteInfo.m_BoundingBoxHeight / 2.0;
				XYZ xyz3;
				if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Left)
				{
					xyz3 = new XYZ(textNoteInfo.m_Position.X + textNoteInfo.m_BoundingBoxWidth / 2.0, textNoteInfo.m_Position.Y, textNoteInfo.m_Position.Z);
				}
				else if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Center)
				{
					xyz3 = textNoteInfo.m_Position;
				}
				else
				{
					xyz3 = new XYZ(textNoteInfo.m_Position.X - textNoteInfo.m_BoundingBoxWidth / 2.0, textNoteInfo.m_Position.Y, textNoteInfo.m_Position.Z);
				}
				if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Top)
				{
					xyz3 -= XYZ.BasisY * (textNoteInfo.m_BoundingBoxHeight / 2.0);
				}
				else if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Bottom)
				{
					xyz3 += XYZ.BasisY * (textNoteInfo.m_BoundingBoxHeight / 2.0);
				}
				XYZ startPoint2 = xyz3 + xyz2 - xyz;
				XYZ endPoint2 = xyz3 - xyz2 + xyz;
				Line line = YJKLineEx.YJKGetBound(startPoint2, endPoint2);
				if (boundingBoxUV == null)
				{
					boundingBoxUV = Geometry.CalculateBoundingBox2D(line);
				}
				else
				{
					BoundingBoxUV box3 = Geometry.CalculateBoundingBox2D(line);
					boundingBoxUV = Geometry.BoundingBoxesMerge(boundingBoxUV, box3);
				}
			}
			return boundingBoxUV;
		}

		protected void DrawLine(Pen pen, Line line, Transform trans)
		{
			XYZ xyz = line.GetEndPoint(0);
			XYZ xyz2 = line.GetEndPoint(1);
			xyz = Geometry.TransformPoint(xyz, trans);
			xyz2 = Geometry.TransformPoint(xyz2, trans);
			PointF pt = new PointF((float)xyz.X, (float)xyz.Y);
			PointF pt2 = new PointF((float)xyz2.X, (float)xyz2.Y);
			this.m_Graphics.DrawLine(pen, pt, pt2);
		}

		protected void DrawLine(Pen pen, XYZ ptS, XYZ ptE, Transform trans)
		{
			ptS = Geometry.TransformPoint(ptS, trans);
			ptE = Geometry.TransformPoint(ptE, trans);
			PointF pt = new PointF((float)ptS.X, (float)ptS.Y);
			PointF pt2 = new PointF((float)ptE.X, (float)ptE.Y);
			this.m_Graphics.DrawLine(pen, pt, pt2);
		}

		protected void DrawArc(Pen pen, Arc arc, Transform trans)
		{
			if (Math.Abs(arc.Length - Math.PI * arc.Radius * 2.0) < 1E-06)
			{
				XYZ center = arc.Center;
				double radius = arc.Radius;
				Arc arc2 = Arc.Create(center, radius, 0.0, Math.PI, XYZ.BasisX, XYZ.BasisY);
				Arc arc3 = Arc.Create(center, radius, Math.PI, Math.PI*2, XYZ.BasisX, XYZ.BasisY);
				this.DrawArc(pen, arc2, trans);
				this.DrawArc(pen, arc3, trans);
				return;
			}
			arc.GetEndPoint(0);
			arc.GetEndPoint(1);
			XYZ center2 = arc.Center;
			float num = (float)(arc.Radius * trans.Scale);
			XYZ normal = arc.Normal;
			double num2 = 0.0;
			double num3 = 0.0;
			Geometry.GetArcAngles(arc, ref num2, ref num3);
			float num4 = 6.28318548f - (float)num3;
			float num5 = 6.28318548f - (float)num2;
			if (num4 > num5)
			{
				num5 += 6.28318548f;
			}
			float num6 = num5 - num4;
			num4 = num4 * 180f / 3.14159274f;
			num6 = num6 * 180f / 3.14159274f;
			XYZ xyz = Geometry.TransformPoint(center2, trans);
			float x = (float)(xyz.X - (double)num);
			float y = (float)(xyz.Y - (double)num);
			float num7 = num * 2f;
			this.m_Graphics.DrawArc(pen, x, y, num7, num7, num4, num6);
		}

		protected void DrawText(TextNoteInfo textNoteInfo, Transform trans)
		{
			if (textNoteInfo.m_Text.CompareTo("") == 0)
			{
				return;
			}
			float emSize = (float)(textNoteInfo.m_Height * trans.Scale);
			Font font = new Font("宋体", emSize);
			SolidBrush brush = new SolidBrush(this.PenColorToColor(textNoteInfo.m_Color));
			XYZ xyz = Geometry.TransformPoint(textNoteInfo.m_Position, trans);
			double num = textNoteInfo.m_BoundingBoxWidth * trans.Scale;
			double num2 = textNoteInfo.m_BoundingBoxHeight * trans.Scale;
			double num3;
			if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Left)
			{
				num3 = xyz.X;
			}
			else if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Center)
			{
				num3 = xyz.X - num / 2.0;
			}
			else
			{
				num3 = xyz.X - num;
			}
			double num4;
			if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Top)
			{
				num4 = xyz.Y;
			}
			else if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Middle)
			{
				num4 = xyz.Y - num2 / 2.0;
			}
			else
			{
				num4 = xyz.Y - num2;
			}
			Rectangle rectangle = new Rectangle((int)num3, (int)num4, (int)num, (int)num2);
			StringFormat stringFormat = new StringFormat();
			stringFormat.LineAlignment = StringAlignment.Center;
			stringFormat.Alignment = StringAlignment.Center;
			XYZ xyz2;
			if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Left)
			{
				xyz2 = new XYZ(xyz.X + num / 2.0, xyz.Y, xyz.Z);
				stringFormat.Alignment = StringAlignment.Near;
			}
			else if (textNoteInfo.m_AlignH == TextNoteInfo.AlignHType.AHT_Center)
			{
				xyz2 = xyz;
				stringFormat.Alignment = StringAlignment.Center;
			}
			else
			{
				xyz2 = new XYZ(xyz.X - num / 2.0, xyz.Y, xyz.Z);
				stringFormat.Alignment = StringAlignment.Far;
			}
			if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Top)
			{
				xyz2 -= XYZ.BasisY * (num2 / 2.0);
				stringFormat.LineAlignment = StringAlignment.Far;
			}
			else if (textNoteInfo.m_AlignV == TextNoteInfo.AlignVType.AVT_Bottom)
			{
				xyz2 += XYZ.BasisY * (num2 / 2.0);
				stringFormat.LineAlignment = StringAlignment.Center;
			}
			else
			{
				stringFormat.LineAlignment = StringAlignment.Near;
			}
			Matrix matrix = new Matrix();
			double num5 = textNoteInfo.m_Angle * 180.0 / Math.PI;
			matrix.RotateAt(-(float)num5, new PointF((float)xyz2.X, (float)xyz2.Y));
			Matrix transform = this.m_Graphics.Transform;
			Matrix transform2 = this.m_Graphics.Transform;
			transform2.Multiply(matrix);
			this.m_Graphics.Transform = transform2;
			this.m_Graphics.FillEllipse(Brushes.White, rectangle);
			this.m_Graphics.DrawString(textNoteInfo.m_Text, font, brush, rectangle, stringFormat);
			this.m_Graphics.Transform = transform;
		}

		private void DrawFillRegion(FillRegion fillRegion, Transform trans)
		{
			try
			{
				List<EdgeInfo> edgeLoop = fillRegion.EdgeLoop;
				List<XYZ> list = new List<XYZ>();
				List<double> list2 = new List<double>();
				double num = 0.0;
				for (int i = 0; i < edgeLoop.Count; i++)
				{
					EdgeInfo edgeInfo = edgeLoop[i];
					num += edgeInfo.Length();
					list.Add(edgeInfo.StartPoint);
					list2.Add(edgeInfo.Bulge);
				}
				double fitSpace = num / (double)edgeLoop.Count / 10.0;
				List<XYZ> list3 = new List<XYZ>();
				Geometry.GetFittingPolyline(list, list2, ref list3, fitSpace);
				for (int i = 0; i < list3.Count; i++)
				{
					list3[i] = Geometry.TransformPoint(list3[i], trans);
				}
				GraphicsPath graphicsPath = new GraphicsPath();
				for (int i = 0; i < list3.Count; i++)
				{
					XYZ xyz = list3[i];
					XYZ xyz2;
					if (i == list3.Count - 1)
					{
						xyz2 = list3[0];
					}
					else
					{
						xyz2 = list3[i + 1];
					}
					graphicsPath.AddLine((float)xyz.X, (float)xyz.Y, (float)xyz2.X, (float)xyz2.Y);
				}
				Brush brush = new SolidBrush(this.PenColorToColor(fillRegion.Color));
				this.m_Graphics.FillRegion(brush, new Region(graphicsPath));
			}
			catch (Exception)
			{
			}
		}

		private List<CurveInfo> m_Curves = new List<CurveInfo>();

		private List<TextNoteInfo> m_TextNotes = new List<TextNoteInfo>();

		private List<FillRegion> m_FillRegions = new List<FillRegion>();

		private Graphics m_Graphics;

        private System.Windows.Forms.Control m_Control;
	}
}
